package com.zl.learning.thread.completable_future;

import org.junit.Test;

import java.util.concurrent.*;

public class CompletableFutureTest {

    public Future<Double> getPriceAsync(String product) {
        CompletableFuture<Double> futurePrice = new CompletableFuture<>();
        new Thread(() -> {
            try {
                double price = calculatePrice(product);
                futurePrice.complete(price);
            } catch (Exception ex) {
                futurePrice.completeExceptionally(ex);
            }
        }).start();
        return futurePrice;
    }

    private double calculatePrice(String product) {
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return 10000;
    }

    private void doSomethingElse() {
        System.out.println("DoSomeThingElse");
    }

    @Test
    public void test0() {
        Future<Double> res = getPriceAsync("aaa");
        try {
            System.out.println(res.get());
            System.out.println("complete");
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void test1() {
        int process = Runtime.getRuntime().availableProcessors();
        System.out.println(process);
    }

    @Test
    public void test2() {
        ExecutorService executor = Executors.newCachedThreadPool();
        Future<Double> future = executor.submit(this::doSomeLongComputation);
        doSomethingElse();
        try {
            Double result = future.get(1, TimeUnit.SECONDS);
            System.out.println(result);
        } catch (ExecutionException ee) {
// 计算抛出一个异常
        } catch (InterruptedException ie) {
// 当前线程在等待过程中被中断
        } catch (TimeoutException te) {
// 在Future对象完成之前超过已过期
        }
    }

    private double doSomeLongComputation() {
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return 2.2;
    }

    @Test
    public void test3() {
        CompletableFuture<Double> res = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 2.2;
        });
        try {
            double a = res.get();
            System.out.println(a);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void test4() throws ExecutionException, InterruptedException {
        CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 2.2;
        }).thenApply(aDouble -> {
            System.out.println(aDouble);
            return aDouble * 2;
        }).get();
    }
}
